<?php

use Swoole\Coroutine;

if (!function_exists('compute')) {
    /**
     * @param       $method
     * @param  int  $scale
     * @param       ...$values
     * @return int|mixed
     */
    function compute($method, int $scale, ...$values)
    {
        $result = $values[0] ?? null;
        array_shift($values);

        foreach ($values as $index => $value) {
            $result = $method($result, $value, $scale + 1);
        }
        return round($result, $scale);
    }
}


if (!function_exists('add')) {
    /**
     * [ + ]
     * @param  int  $scale
     * @param       ...$values
     * @return int|mixed
     */
    function add(int $scale, ...$values)
    {
        return compute('bcadd', $scale, ...$values);
    }
}

if (!function_exists('sub')) {
    /**
     * [ - ]
     * @param  int  $scale
     * @param       ...$values
     * @return int|mixed
     */
    function sub(int $scale, ...$values)
    {
        return compute('bcsub', $scale, ...$values);
    }
}

if (!function_exists('mul')) {
    /**
     * [ * ]
     * @param  int  $scale
     * @param       ...$values
     * @return int|mixed
     */
    function mul(int $scale, ...$values)
    {
        return compute('bcmul', $scale, ...$values);
    }
}

if (!function_exists('div')) {
    /**
     * [ / ]
     * @param  int  $scale
     * @param       ...$values
     * @return int|mixed
     */
    function div(int $scale, ...$values)
    {
        return in_array(0, $values) ? 0 : compute('bcdiv', $scale, ...$values);
    }
}


if (!function_exists('build_friendly_tips')) {
    /**
     * @param          $data
     * @param  string  $message
     * @param  int     $business_type_target_id
     * @param  string  $target_field
     */
    function build_friendly_tips(
        &$data,
        string $message,
        int $business_type_target_id,
        string $target_field = 'id'
    ) {
        $data['message'] = $message;
        $data['target_field'] = $target_field;
        $data['business_type_target_id'] = $business_type_target_id;
    }
}


if (!function_exists('___')) {
    /**
     * @param  string|null  $key
     * @param  array        $replace
     * @param  null         $locale
     * @return array|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Translation\Translator|string|null
     */
    function ___(string $key = null, $replace = [], $locale = null)
    {
        $value = __("trawind::common.$key", $replace, $locale);
        return \Illuminate\Support\Str::contains($value, 'trawind::') ? $key : $value;
    }
}


if (!function_exists('__date_time')) {
    /**
     * @param $datetime
     * @return mixed|string
     */
    function __date_time($datetime)
    {
        if ($datetime === 0) {
            return '';
        }
        if (!is_null($datetime)) {
            $timeZoneKey = \Trawind\ConfigCenter\Helpers\ConfigHelper::resolve('time_zone');
            $timeZone = \Trawind\ConfigCenter\Enums\TimeZone::MESSAGE_MAP[$timeZoneKey]['key'] ?? 'GMT';
            $datetime = \Carbon\Carbon::parse($datetime)
                ->setTimezone($timeZone)
                ->toDateTimeString();
        }

        return $datetime;
    }
}


if (!function_exists('__trans')) {
    /**
     * @param  string|null  $key
     * @param  string       $module
     * @param  array        $replace
     * @param  null         $locale
     * @return array|bool|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Translation\Translator|string|null
     */
    function __trans(string $key = null, string $module = '', $replace = [], $locale = null)
    {
        if (($value = ___($key, $replace, $locale)) == $key) {
            $common = __("common.$key", $replace, $locale);
            $value = \Illuminate\Support\Str::contains($common, "common.") ? $key : $common;

            if ($value == $key) {
                $_value = __("$module.$key", $replace, $locale);
                $value = \Illuminate\Support\Str::contains($_value, "$module.") ? $key : $_value;
            }
        }

        return $value;
    }
}


if (!function_exists('__trans_list')) {
    /**
     * @param  array  $data
     * @return array
     */
    function __trans_list(array $data)
    {
        return array_map('__trans', $data);
    }
}

if (!function_exists('_encrypt')) {
    /**
     * @param  string  $string
     * @param  string  $key
     * @return string
     */
    function _encrypt(string $string, string $key = 'trawindcloud')
    {
        // Remove the base64 encoding from our key
        $encryption_key = base64_decode($key);
        // Generate an initialization vector
        $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
        // Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector.
        $encrypted = openssl_encrypt($string, 'aes-256-cbc', $encryption_key, 0, $iv);
        // The $iv is just as important as the key for decrypting, so save it with our encrypted data using a unique separator (::)
        return base64_encode($encrypted.'::'.$iv);
    }
}

if (!function_exists('_decrypt')) {
    /**
     * @param  string  $string
     * @param  string  $key
     * @return false|string
     */
    function _decrypt(string $string, string $key = 'trawindcloud')
    {
        // Remove the base64 encoding from our key
        $encryption_key = base64_decode($key);
        // To decrypt, split the encrypted data from our IV - our unique separator used was "::"
        [$encrypted_data, $iv] = explode('::', base64_decode($string), 2);
        return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
    }
}


if (!function_exists('mb_unserialize')) {
    /**
     * mb_unserialize function
     *
     * @param  string  $str
     * @return void
     */
    function mb_unserialize(?string $str)
    {
        if (!$str) {
            return $str;
        }
        return preg_replace_callback('#s:(\d+):"(.*?)";#s', function ($match) {
            return 's:'.strlen($match[2]).':"'.$match[2].'";';
        }, $str);
    }
}

if (!function_exists('RedisManager')) {
    function RedisManager()
    {
        return \Trawind\Helpers\SystemHelper::redis();
    }
}

if (!function_exists('setNeedDataPermission')) {
    function setNeedDataPermission($default = true)
    {
        app()->bind('dataPermissionNeedExecuteStatus', function () use ($default) {
            return $default;
        });
    }
}

if (!function_exists('getNeedDataPermission')) {
    function getNeedDataPermission()
    {
        try {
            return app('dataPermissionNeedExecuteStatus');
        } catch (\Throwable $th) {
            return true;
        }
    }
}

if (!function_exists('runningInConsole')) {
    function runningInConsole()
    {
        if (app()->runningInConsole() && Coroutine::getuid() < 0) 
            return true;
        return false;
    }
}